package com.peg.dataobjects;

import com.peg.rules.Rule;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author sad
 */
public class Context {
    private ValueStackList _stackList;
    private char[] _stream;
    private int _currentStreamIndex;
    private int _matchStartPosition;
    private int _matchLength;
    private boolean _invert = false;
    private int _lastIterationCount;
    private List<ParsingError> errorsList;
    private Map<String, Rule> rulesMap;

    public Context() {
        _stackList = new ValueStackList();
        errorsList = new ArrayList<ParsingError>(10);
    }

    public void setRulesMap(Map<String, Rule> rulesMap) {
        this.rulesMap = rulesMap;
    }

    public Rule getRule(String ruleName) {
        return rulesMap.get(ruleName);
    }

    public void addError(ParsingError error) {
        errorsList.add(error);
    }

    public int errorsCount() {
        return errorsList.size();
    }

    public ParsingError getError(int i) {
        return errorsList.get(i);
    }

    public int getlastIterationsCount() {
        return _lastIterationCount;
    }

    public void setLastIterationsCount(int lastIterationsCount) {
        _lastIterationCount = lastIterationsCount;
    }

    public boolean isInvert() {
        return _invert;
    }

    public void setInvert(boolean invert) {
        _invert = invert;
    }

    public void clearStackList() {
        getStacksList().Clear();
    }

    public void setStream(String stream, boolean clearContext) {
        _stream = stream.toCharArray();
        _currentStreamIndex = 0;
        setMatch(0, 0);
        if (clearContext) {
            _stackList = new ValueStackList();
        }
    }

    private ValueStackList getStacksList() {
        return _stackList;
    }

    public ValueStack getStack() {
        return getStacksList().PeekValueStack();
    }

    public void push(Object value) {
        getStack().Push(value);
    }

    public Object pop() {
        return getStack().Pop();
    }

    public Object pop(int position) {
        ValueStack st = getStack();
        return st.Pop(position);
    }

    public String popObjectWithThePrefix(String prefix) {
        ValueStack st = getStack();
        return st.PopStringWithThePrefix(prefix);
    }

    public void inLevel() {
        getStacksList().CloneValueStack();
    }

    public void outLevel(boolean saveValueStack) {
        if (saveValueStack) {
            getStacksList().PopButSaveLastValueStack();
        } else {
            getStacksList().DiscardValueStack();
        }
    }

    public int getCurrentStreamIndex() {
        return _currentStreamIndex;
    }

    public void setCurrentStreamIndex(int currentStreamIndex) {
        _currentStreamIndex = currentStreamIndex;
    }

    public boolean EOL() {
        if (getCurrentStreamIndex() >= _stream.length) {
            return true;
        }

        return false;
    }

    public char getNextChar() {
        if (_currentStreamIndex >= _stream.length) {
            return (char) 0;
        }

        char c = _stream[_currentStreamIndex];
        _currentStreamIndex++;
        return c;
    }

    private int getMatchStartPosition() {
        return _matchStartPosition;
    }

    private int getMatchLength() {
        return _matchLength;
    }

    public void setMatch(int startPosition, int length) {
        _matchStartPosition = startPosition;
        _matchLength = length;
    }

    public String getMatch() {
        return new String(_stream, getMatchStartPosition(), getMatchLength());
    }
}
